#pragma once

#include <string>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <memory>
#include <unordered_set>

using std::string;
using std::map;
using std::vector;
using std::pair;
using std::priority_queue;
using std::unique_ptr;
using std::shared_ptr;
using std::unordered_set;

const string index_en_lib_filename = "../../../data/en_index.dat";
const string dict_en_lib_filename = "../../../data/en_dict.dat";
const string index_cn_lib_filename = "../../../data/cn_index.dat";
const string dict_cn_lib_filename = "../../../data/cn_dict.dat";
const string stop_word_cn_filename = "../../../data/stopwords/cn_stopwords.txt";
const string stop_word_en_filename = "../../../data/stopwords/en_stopwords.txt";

class CandidateWordSet
{
public:
    // 进行构造单例
    static CandidateWordSet &getCandidateWordSet();
    string process(const string &word, int topK = 5);
                    
    // 进行设置候选索引集
    CandidateWordSet(const CandidateWordSet &) = delete;
    CandidateWordSet &operator=(const CandidateWordSet &) = delete;

private:
    // 只保留一个 setCandiateIndexSet 声明
    void setCandiateIndexSet(const string &word);
    string getCandidateWords(int topK = 5);
    CandidateWordSet();
    ~CandidateWordSet();
    
    void load_en_index_set(const string &index_en_lib_file = index_en_lib_filename);
    void load_en_dict_set(const string &dict_en_lib_file = dict_en_lib_filename);

    void load_cn_index_set(const string &index_cn_lib_file = index_cn_lib_filename);
    void load_cn_dict_set(const string &dict_cn_lib_file = dict_cn_lib_filename);

    void load_cn_stop_word_set(const string &stop_word_lib_file = stop_word_cn_filename);
    void load_en_stop_word_set(const string &stop_word_lib_file = stop_word_en_filename);

    void create_en_keyword_set(const string &word);
    void create_cn_keyword_set(const string &word);
    
    int CalculateEditDistance(const string word1, const string word2);

public:
    struct Candidate
    {
        std::string word; // 单词
        int edit_distance; // 编辑距离
        int frequency; // 频率
        
        bool operator<(const Candidate& other) const
        { 
            if(this->edit_distance != other.edit_distance)
            {
                return this->edit_distance < other.edit_distance;
            }
            return this->frequency < other.frequency;
        }
    };

private:
    string m_word; // 输入的单词
    int m_cn_sum;
    int m_en_sum;
     
    unique_ptr<unordered_set<string>> m_cn_stop_words; // 中文停用词表
    unique_ptr<unordered_set<string>> m_en_stop_words; // 英文停用词表

    // 英文索引和字典
    shared_ptr<map<string, vector<int>>> m_en_indexes;
    shared_ptr<vector<pair<string, int>>> m_en_dict;

    // 中文索引和字典
    shared_ptr<map<string, vector<int>>> m_cn_indexes;
    shared_ptr<vector<pair<string, int>>> m_cn_dict;

    unique_ptr<map<string, vector<int>>> m_indexes_word; // 索引表
    shared_ptr<priority_queue<Candidate, vector<Candidate>, std::less<Candidate>>> m_candidate_words; // 优先队列
};